﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Text;
using Pahan.McuFusion.Common;
using Pahan.McuFusion.Common.Utils;
using Pahan.McuFusion.FusionBoot.Atmel.AVR;

namespace Pahan.McuFusion.FusionBoot
{
    [Serializable]
    public class FusionBootProgrammerInfo : ProgrammerInfo
    {
        #region Overrides of BaseInfo

        public override string Name
        {
            get { return "FusionBoot Programmer"; }
        }

        public override string Description
        {
            get { return String.Empty; }
        }

        #endregion

        #region Overrides of ProgrammerInfo

        /// <summary>
        /// Gets the list of the supported microcontrollers.
        /// </summary>
        public override IList<DeviceInfo> SupportedMicrocontrollers
        {
            get 
            {
                if (supportedDevices == null)
                {
                    supportedDevices = FindSupportedDevices();
                }
                return supportedDevices.Cast<DeviceInfo>().ToList().AsReadOnly();
            }
        }

        /// <summary>
        /// Creates an instance of the programmer.
        /// </summary>
        /// <param name="mcu">Target microcontroller.</param>
        /// <param name="adapter">Target adapter.</param>
        /// <returns></returns>
        public override IProgrammer CreateProgrammer(DeviceInfo mcu, IHardwareAdapter adapter)
        {
            Assert.NotNull(mcu, "mcu");
            Assert.NotNull(adapter, "adapter");
            Assert.OfType<FusionBootMcuInfo>(mcu, "mcu");
            Assert.OfType<IFusionBootAdapter>(adapter, "adapter");
            return new FusionBootProgrammer((FusionBootMcuInfo)mcu, this, (IFusionBootAdapter)adapter);
        }

        /// <summary>
        /// Checks whethes the specified hardware adapter is supported by the programmer.
        /// </summary>
        public override bool Supports(HardwareAdapterInfo hardwareAdapter)
        {
            return hardwareAdapter.Implements<IFusionBootAdapter>();
        }

        #endregion

        #region Supported MCU's

        private IList<FusionBootMcuInfo> FindSupportedDevices()
        {
            var devices = new List<FusionBootMcuInfo>();
            var types = AssemblyLoader.GetTypes<FusionBootMcuInfo>();
            foreach (var type in types)
            {
                try
                {
                    var method = type.GetMethod("GetAllDevices");
                    var newDevices = (IList<FusionBootMcuInfo>)method.Invoke(null, null);
                    devices.AddRange(newDevices);
                }
                catch
                {
                    
                }
            }
            return devices;
        }

        private IList<FusionBootMcuInfo> supportedDevices = null;

        #endregion
    }
}
